package main

import (
	"crypto/tls"
	"encoding/base64"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"net/http/cookiejar"
	"net/url"
	"time"
)

func main() {
	var err error

	//加载ESNI密钥
	var esniKeys *tls.ESNIKeys
    var esniPrivateKey []byte
	esniPrivateKey, err = ioutil.ReadFile("esni")
	if err != nil {
		log.Fatalf("Failed to read ESNI private key: %s", err)
	}
	contents, err := ioutil.ReadFile("esni.pub")
	if err != nil {
		log.Fatalf("Failed to read ESNIKeys: %s", err)
	}
	esniKeysBytes, err := base64.StdEncoding.DecodeString(string(contents))
	if err != nil {
		log.Fatal("Bad -esni-keys: %s", err)
	}
	esniKeys, err = tls.ParseESNIKeys(esniKeysBytes)
	if esniKeys == nil {
		log.Fatalf("Cannot parse ESNIKeys: %s", err)
	}

	//配置TLS
	tlsConfig := &tls.Config{
		GetCertificate:getCertificateForSNI,
		MinVersion:       tls.VersionTLS13,
		MaxVersion:       tls.VersionTLS13,
		CurvePreferences: []tls.CurveID{},
		GetServerESNIKeys:func([]byte) (*tls.ESNIKeys, []byte, error) { return esniKeys, esniPrivateKey, nil },
		Accept0RTTData: true,
	}

	//创建一个http.server实例
	server := &http.Server{
		Addr: ":443",
		TLSConfig: tlsConfig,
	}

	// 注册 DoH 请求处理函数
	http.HandleFunc("/proxy", handleHttpsRequest)

	// 启动 HTTPS 服务器
	log.Println("Starting DoH server on https://localhost:443")
	if err := server.ListenAndServeTLS("", ""); err != nil {
		log.Fatal("ListenAndServeTLS: ", err)
	}


}

func getCertificateForSNI(helloInfo *tls.ClientHelloInfo) (*tls.Certificate, error) {
	switch helloInfo.ServerName {
    case "server1.com":
        cert, err := tls.LoadX509KeyPair("server1.crt", "server1.key")
        return &cert, err  // 返回结构体的指针
    case "server2.com":
        cert, err := tls.LoadX509KeyPair("server2.crt", "server2.key")
        return &cert, err  // 返回结构体的指针
    default:
        return nil, fmt.Errorf("no certificate found for SNI: %s", helloInfo.ServerName)
    }
}

func handleHttpsRequest(w http.ResponseWriter, req *http.Request) {
	targetURL := req.Header.Get("X-Target-URL")
	if targetURL == "" {
		http.Error(w, "缺少 X-Target-URL 请求头", http.StatusBadRequest)
		return
	}

	parsedURL, err := url.Parse(targetURL)
	if err != nil {
		http.Error(w, "无效的目标URL", http.StatusBadRequest)
		return
	}

	// 构造新请求
	proxyReq, _ := http.NewRequest(req.Method, targetURL, req.Body)
	proxyReq.Header = req.Header.Clone()
	proxyReq.Header.Del("Host")
	proxyReq.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36")
	proxyReq.Header.Set("Accept-Language", "en-US,en;q=0.9")
	proxyReq.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8")
	proxyReq.Header.Set("Referer", "https://www.google.com/")
	proxyReq.Host = parsedURL.Host // 修正Host头

	// 安全配置TLS客户端
	jar, _ := cookiejar.New(nil) // Cookie持久化
	client := &http.Client{
		Jar: jar,
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, // 生产环境应使用有效证书
		},
		Timeout: 10 * time.Second,
	}

	// 转发请求
	resp, err := client.Do(proxyReq)
	if err != nil {
		http.Error(w, "转发请求失败: "+err.Error(), http.StatusBadGateway)
		return
	}
	defer resp.Body.Close()

	// 回传响应头
	for k, v := range resp.Header {
		w.Header()[k] = v
	}
	w.WriteHeader(resp.StatusCode)

	// 回传响应内容
	if _, err := io.Copy(w, resp.Body); err != nil {
		log.Printf("响应回传错误: %v", err)
	}
}
